"""
Assessment Plan 核心业务逻辑
处理业务规则和数据转换，调用CRUD操作执行数据库交互
"""
from typing import Dict, Any, Optional, List
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession

from schemas.assessmentPlan import (
    AssessmentPlanCreate,
    AssessmentPlanUpdate,
    AssessmentPlanResponse,
    AssessmentPlanPagination
)
from schemas.complianceItem import ComplianceItemCreate
from crud import assessmentPlan as assessment_plan_crud
from crud import complianceTemplate as compliance_template_crud
from crud import complianceItem as compliance_item_crud
from core import complianceItem as compliance_item_service
from log import log_info, log_error
from fastapi import HTTPException

async def get_assessment_plans(
    db: AsyncSession,
    skip: int = 0,
    limit: int = 100,
    filters: Optional[Dict[str, Any]] = None
) -> AssessmentPlanPagination:
    """
    获取评估计划列表，支持分页和过滤
    同时计算每个评估计划的完成状态（如果所有关联的合规项都已完成，则评估计划状态为completed）

    Args:
        db: 数据库会话
        skip: 跳过记录数
        limit: 返回记录限制
        filters: 过滤条件字典

    Returns:
        包含总记录数和评估计划列表的分页响应对象
    """
    items, total = await assessment_plan_crud.get_assessment_plans(db, skip, limit, filters)
    
    # 更新每个评估计划的状态
    for plan in items:
        # 获取该评估计划下的所有合规项
        all_items, _ = await compliance_item_crud.get_compliance_items(
            db,
            filters={
                "assessment_plan_id": plan.id
            }
        )
        
        # 检查是否有任何未完成的合规项
        has_incomplete_items = any(item.progress_status != 'completed' for item in all_items)
        
        # 如果没有未完成的合规项，则更新状态为completed
        if not has_incomplete_items and plan.status != 'completed' and all_items:
            plan.status = 'completed'
            # 保存状态更新到数据库
            await db.commit()
            await db.refresh(plan)

        # 如果有未完成的合规项，则更新状态为in_progress
        elif has_incomplete_items and plan.status != 'in_progress' and all_items:
            plan.status = 'in_progress'
            # 保存状态更新到数据库
            await db.commit()
            await db.refresh(plan)

    return AssessmentPlanPagination(
        total=total,
        items=items
    )

async def get_assessment_plan(db: AsyncSession, plan_id: UUID) -> Optional[AssessmentPlanResponse]:
    """
    根据ID获取评估计划

    Args:
        db: 数据库会话
        plan_id: 评估计划ID

    Returns:
        评估计划响应对象，未找到则返回None
    """
    plan = await assessment_plan_crud.get_assessment_plan_by_id(db, plan_id)
    if plan is None:
        return None
    
    return AssessmentPlanResponse.model_validate(plan)

async def create_assessment_plan(db: AsyncSession, plan_data: AssessmentPlanCreate) -> AssessmentPlanResponse:
    """
    创建新的评估计划

    Args:
        db: 数据库会话
        plan_data: 评估计划创建数据

    Returns:
        创建的评估计划响应对象
        
    Raises:
        HTTPException: 如果已存在相同名称和评估类型的评估计划
    """
    log_info(f"Creating new assessment plan: {plan_data.name}", module="core.assessmentPlan")
    
    # 检查是否已存在相同名称和评估类型的评估计划
    existing_plan = await assessment_plan_crud.get_assessment_plan_by_name_and_type(
        db, plan_data.name, plan_data.assessment_type
    )
    if existing_plan:
        log_error(f"Assessment plan with name '{plan_data.name}' and type '{plan_data.assessment_type}' already exists", 
                module="core.assessmentPlan")
        raise HTTPException(
            status_code=400,
            detail=f"已存在名称为'{plan_data.name}'且评估类型为'{plan_data.assessment_type}'的评估计划"
        )
    
    # 创建评估计划记录
    plan = await assessment_plan_crud.create_assessment_plan(db, plan_data)
    
    # 根据评估计划类型，从合规模板中获取并创建对应的合规项
    try:
        await _create_compliance_items_from_template(db, plan)
        log_info(f"Created compliance items for assessment plan: {plan.id}", module="core.assessmentPlan")
    except Exception as e:
        log_error(f"Failed to create compliance items for assessment plan {plan.id}: {str(e)}", 
                 module="core.assessmentPlan")
    
    return AssessmentPlanResponse.model_validate(plan)

async def update_assessment_plan(
    db: AsyncSession,
    plan_id: UUID,
    plan_data: AssessmentPlanUpdate
) -> Optional[AssessmentPlanResponse]:
    """
    更新评估计划

    Args:
        db: 数据库会话
        plan_id: 评估计划ID
        plan_data: 更新数据

    Returns:
        更新后的评估计划响应对象，未找到则返回None
    """
    log_info(f"Updating assessment plan with ID: {plan_id}", module="core.assessmentPlan")
    
     # 检查是否已存在相同名称和评估类型的评估计划
    existing_plan = await assessment_plan_crud.get_assessment_plan_by_name_and_type(
        db, plan_data.name, plan_data.assessment_type
    )
    if existing_plan:
        log_error(f"Assessment plan with name '{plan_data.name}' and type '{plan_data.assessment_type}' already exists", 
                module="core.assessmentPlan")
        raise HTTPException(
            status_code=400,
            detail=f"已存在名称为'{plan_data.name}'且评估类型为'{plan_data.assessment_type}'的评估计划"
        )
    
    # 更新评估计划
    updated_plan = await assessment_plan_crud.update_assessment_plan(db, plan_id, plan_data)
    if updated_plan is None:
        return None
    
    return AssessmentPlanResponse.model_validate(updated_plan)

async def delete_assessment_plan(db: AsyncSession, plan_id: UUID) -> bool:
    """
    删除评估计划

    Args:
        db: 数据库会话
        plan_id: 评估计划ID

    Returns:
        删除成功返回True，未找到则返回False
    """
    log_info(f"Deleting assessment plan with ID: {plan_id}", module="core.assessmentPlan")
    
    # 删除评估计划
    return await assessment_plan_crud.delete_assessment_plan(db, plan_id)


async def _create_compliance_items_from_template(db: AsyncSession, plan: AssessmentPlanCreate) -> None:
    """
    从合规模板中创建合规项

    Args:
        db: 数据库会话
        plan: 评估计划对象
    """
    # 查询与评估计划类型匹配的模板
    template_items = await _get_template_items_by_assessment_template_id(db, plan.template_id)
    
    if not template_items:
        log_info(f"No template items found for assessment type: {plan.assessment_type}", 
               module="core.assessmentPlan")
        return
    
    # 如果评估类型为数据安全评估，只取maturity_level为1的模版项
    # 其他评估类型，使用全部模版项，不进行过滤
    if plan.assessment_type == '105':
        compliance_template = await compliance_template_crud.get_compliance_template_by_id(db, plan.template_id)
        log_info(f"数据安全评估模版：{compliance_template.name}，默认成熟度等级：{compliance_template.default_maturity_level}", module="core.assessmentPlan")
        template_items = [item for item in template_items if item.get("maturity_level") == compliance_template.default_maturity_level]


    # 从模板项创建合规项
    compliance_items = []
    for template in template_items:
        compliance_item = ComplianceItemCreate(
            assessment_plan_id=plan.id,
            title=template.get("title", ""),
            description=template.get("description"),
            guide=template.get("guide"),
            compliance_type=template.get("compliance_type"),
            maturity_level=template.get("maturity_level"),
            source_type = 'system',
            risk_level="low",
            inspector="",  # 默认为空，后续可由用户指定
            compliance_status="non-compliant",  # 默认为不合规
            progress_status="in-progress"  # 默认为进行中
        )
        compliance_items.append(compliance_item)
    
    if compliance_items:
        await  compliance_item_service.bulk_create_compliance_items(db, compliance_items)
        log_info(f"Created {len(compliance_items)} compliance items for plan ID: {plan.id}", 
               module="core.assessmentPlan")


async def _get_template_items_by_assessment_template_id(db: AsyncSession, template_id: UUID) -> List[Dict[str, Any]]:
    """
    根据模板ID获取模板项

    Args:
        db: 数据库会话
        template_id: 模板ID

    Returns:
        模板项列表
    """
    log_info(f"从模板ID: {template_id}获取模板项", module="core.assessmentPlan")
    
    try:
        
        # 1. 获取模板对应的所有模板项
        template_items = await compliance_template_crud.get_template_items(db, template_id)
        
        if not template_items:
            log_info(f"没有找到模板项，从模板ID: {template_id}", 
                  module="core.assessmentPlan")
            return []
        
        # 2. 转换为所需的字典格式
        result = []
        for item in template_items:
            item_dict = {
                "title": item.title,
                "description": item.description,
                "guide": item.guide,
                "compliance_type": item.compliance_type,
                "maturity_level": item.maturity_level
            }
            
            result.append(item_dict)
        
        log_info(f"从模板ID: {template_id}获取到{len(result)}个模板项", 
               module="core.assessmentPlan")
        return result
        
    except Exception as e:
        log_error(f"从模板ID: {template_id}获取模板项失败: {str(e)}", 
                module="core.assessmentPlan")
        # 如果出现错误，返回空列表          
        return []
